#include "Pokemon.h"
#include "SDLScene.h"

using namespace std;

Pokemon::Pokemon(const PokemonData& _data, int _level)
	: m_Number(_data.number), m_Name(_data.name), m_CanEvolve(_data.canEvolve), m_EvolveLevel(_data.evolveLevel),
	m_Level(_level), m_Waiting(false),  m_Accuracy(1.0f), m_CurrentXP(0), m_NextAttack(-1), m_Attacked(false)
{
	for(int i = 0; i < STAT_COUNT; i++)
	{
		m_IVs[i] = rand() % 16;
		m_EVs[i] = 0;
	}
	
	m_Types.push_back(_data.type1);
	m_Types.push_back(_data.type2);

	SetBaseStats(_data);
	SetCurrentStats();
	SetPokemonAttacks();
}

Pokemon::Pokemon(const Pokemon& _source)
	: m_Number(_source.m_Number), m_Name(_source.m_Name), m_Health(_source.m_Health), m_Attack(_source.m_Attack), m_Defense(_source.m_Defense), m_SpAttack(_source.m_SpAttack), 
	m_SpDefense(_source.m_SpDefense), m_Speed(_source.m_Speed), m_CanEvolve(_source.m_CanEvolve), m_EvolveLevel(_source.m_EvolveLevel), m_Level(_source.m_Level), m_Waiting(_source.m_Waiting),
	m_Accuracy(_source.m_Accuracy), m_CurrentXP(_source.m_CurrentXP), m_NextAttack(_source.m_NextAttack), m_Attacked(_source.m_Attacked)
{
	for(int i = 0; i < _source.m_Types.size(); i++)
	{
		m_Types.push_back(_source.m_Types[i]);
	}

	for(int i = 0; i < _source.m_Attacks.size(); i++)
	{
		m_Attacks.push_back(_source.m_Attacks[i]);
	}

	for(int i = 0; i < _source.m_Statuses.size(); i++)
	{
		StatusAilmentData newStatus = {_source.m_Statuses[i].status, _source.m_Statuses[i].maxTurnAffected, _source.m_Statuses[i].turnAffected};
		m_Statuses.push_back(newStatus);
	}

	for(int i = 0; i < STAT_COUNT; i++)
	{
		m_IVs[i] = _source.m_IVs[i];
		m_EVs[i] = _source.m_EVs[i];
	}

	SetCurrentStats();
}

ostream& operator<<(ostream& _out, const Pokemon& _source)
{
	_out << "# " << _source.GetNumber() << "\t" << _source.GetName() << endl;
	_out << "Lvl " << _source.GetLevel() << "\t" << _source.GetCurrentHP() << " / " << _source.GetMaxHP() << endl;

	return _out;
}

Pokemon& Pokemon::operator=(const Pokemon& _source)
{
	m_Number = _source.m_Number;
	m_Name = _source.m_Name;
	m_Health = _source.m_Health;
	m_Attack = _source.m_Attack;
	m_Defense = _source.m_Defense;
	m_SpAttack = _source.m_SpAttack;
	m_SpDefense = _source.m_SpDefense;
	m_Speed = _source.m_Speed;
	m_CanEvolve = _source.m_CanEvolve;
	m_Level = _source.m_Level;
	m_Waiting = _source.m_Waiting;
	m_Attacked = _source.m_Attacked;
	m_EvolveLevel = _source.m_EvolveLevel;
	m_Accuracy = _source.m_Accuracy;
	m_NextAttack = _source.m_NextAttack;

	m_CurrentHealth = _source.m_CurrentHealth;
	m_CurrentAttack = _source.m_CurrentAttack;
	m_CurrentDefense = _source.m_CurrentDefense;
	m_CurrentSpAttack = _source.m_CurrentSpAttack;
	m_CurrentSpDefense = _source.m_CurrentSpDefense;
	m_CurrentSpeed = _source.m_CurrentSpeed;
	m_CurrentXP = _source.m_CurrentXP;
	
	m_Types.clear();
	m_Attacks.clear();
	m_Statuses.clear();

	for(int i = 0; i < _source.m_Types.size(); i++)
	{
		m_Types.push_back(_source.m_Types[i]);
	}

	for(int i = 0; i < _source.m_Attacks.size(); i++)
	{
		m_Attacks.push_back(_source.m_Attacks[i]);
	}

	for (int i = 0; i < _source.m_Statuses.size(); i++)
	{
		StatusAilmentData newStatus = {_source.m_Statuses[i].status, _source.m_Statuses[i].maxTurnAffected, _source.m_Statuses[i].turnAffected};
		m_Statuses.push_back(newStatus);
	}

	for(int i = 0; i < STAT_COUNT; i++)
	{
		m_IVs[i] = _source.m_IVs[i];
		m_EVs[i] = _source.m_EVs[i];
	}

	return *this;
}

bool Pokemon::operator==(const Pokemon& _source) const
{
	return (m_Name == _source.m_Name) && (m_Level == _source.m_Level) && (m_Number == _source.m_Number) && (m_CurrentXP == _source.m_CurrentXP) && 
		(m_IVs[HP_INDEX] == _source.m_IVs[HP_INDEX]) && (m_IVs[ATK_INDEX] == _source.m_IVs[ATK_INDEX]) && (m_IVs[DEF_INDEX] == _source.m_IVs[DEF_INDEX]) && 
		(m_IVs[SPATK_INDEX] == _source.m_IVs[SPATK_INDEX]) && (m_IVs[SPDEF_INDEX] == _source.m_IVs[SPDEF_INDEX]) && (m_IVs[SPD_INDEX] == _source.m_IVs[SPD_INDEX]);
}

Pokemon::~Pokemon()
{

}

void Pokemon::InitPokemon()
{
	SetCurrentStats();
	RemoveAllStatus();
	m_Waiting = false;

	for(int i = 0; i < m_Attacks.size(); i++)
	{
		m_Attacks[i].InitAttack();
	}
}

void Pokemon::SetBaseStats(const PokemonData& _data)
{
	m_Health = HPCalculation(_data.hp, HP_INDEX);
	m_Attack = StatCalculation(_data.attack, ATK_INDEX);
	m_Defense = StatCalculation(_data.defense, DEF_INDEX);
	m_SpAttack = StatCalculation(_data.spAttack, SPATK_INDEX);
	m_SpDefense = StatCalculation(_data.spDefense, SPDEF_INDEX);
	m_Speed = StatCalculation(_data.speed, SPD_INDEX);
}

void Pokemon::SetPokemonAttacks()
{
	vector<LevelUpData> levelUpChart = PokemonLoader::GetInstance()->GetLevelUpChart(m_Number);

	int count = 0;
	while(count < levelUpChart.size() && levelUpChart[count].level <= m_Level)
	{
		PokemonAttack newAttack = PokemonAttack(PokemonLoader::GetInstance()->GetAttackData(levelUpChart[count].attack));
		if(m_Attacks.size() < MAX_POKEMON_ATTACK)
			m_Attacks.push_back(newAttack);
		else
			m_Attacks[count % MAX_POKEMON_ATTACK] = newAttack;
		count++;
	}
}

queue<string> Pokemon::Attack(PokemonAttack& _attack, Pokemon& _enemy)
{
	stringstream ss;
	ClearOutput();

	int damage;
	int accuracy = rand() % 101;
	_attack.UseAttack();

	if(accuracy <= _attack.GetAttackData().accuracy * m_Accuracy)
	{
		switch(_attack.GetAttackData().status)
		{
		case BURN:
		case FREEZE:
		case PARALYZE:
		case POISONED:
		case SLEEP:
		case CONFUSE:
		case FLINCH:
		case FAINT:
			if(_attack.GetAttackData().targetOther)
				_enemy.InflictStatus(_attack.GetAttackData(), m_Out);
			else
				InflictStatus(_attack.GetAttackData(), m_Out);
			break;
		case ACY_NERF:
		case ATK_NERF:
		case DEF_NERF:
		case SPD_NERF:
		case SP_NERF:
			_enemy.InflictStatModifier(_attack.GetAttackData(), m_Out);
			break;
		case ACY_BOOST:
		case ATK_BOOST:
		case DEF_BOOST:
		case SPD_BOOST:
		case SP_BOOST:
			InflictStatModifier(_attack.GetAttackData(), m_Out);
			break;
		case HEAL:
		{
			float healPercent = _attack.GetAttackData().statusValue/ 100.0f;
			Heal(m_Health * healPercent);
			break;
		}
		case STAND_BY:
			m_Waiting = true;
			m_NextAttack = GetAttackIndex(_attack.GetAttackData().name);
		default:
			break;
		}

		if(!m_Waiting)
		{
			if(_attack.GetAttackData().status == FIX_DAMAGE)
			{
				ss.str("");
				ss << m_Name << " inflicted " << _attack.GetAttackData().statusValue << " damage";
				m_Out.push(ss.str());

				_enemy.InflictDamage(_attack.GetAttackData().statusValue, m_Out);
			}
			else if (_attack.GetAttackData().power != 0)
			{
				damage = DamageCalculation(_attack, _enemy);
		
				if(IsAffectedBy(BURN) && _attack.IsPhysical())
					damage /= 2;
					
				ss.str("");
				ss << m_Name << " inflicted " << damage << " damage";
				m_Out.push(ss.str());

				_enemy.InflictDamage(damage, m_Out);
			}
		}

		switch(_attack.GetAttackData().status)
		{
		case RECOIL:
			if(_attack.GetAttackData().statusValue > 100)
				InflictDamage(m_CurrentHealth, m_Out);
			else if(damage != 0)
			{
				float recoilPercent = _attack.GetAttackData().statusValue / 100.0f;
				InflictDamage(damage * recoilPercent, m_Out);
			}
			break;
		case DRAIN:
			if(damage != 0)
			{
				float healPercent = _attack.GetAttackData().statusValue / 100.0f;
				Heal(damage * healPercent);
			}
			break;
		default:
			break;
		}
	}
		
	if(_attack.GetAttackData().status == COOLDOWN)
		m_Waiting = true;

	_attack.InitAttackStatus();
	return m_Out;
}

queue<string> Pokemon::EndTurnStatus()
{
	stringstream ss;
	ClearOutput();

	for(int i = m_Statuses.size() - 1; i >= 0; i--)
	{
		switch(m_Statuses[i].status)
		{
		case BURN:
			ss.str("");
			ss << m_Name << " is burned";
			m_Out.push(ss.str());
			
			InflictDamage(m_Health / 8.0f, m_Out);
			break;
		case POISONED:
			ss.str("");
			ss << m_Name << " is poisoned";
			m_Out.push(ss.str());
			
			InflictDamage(m_Health / 8.0f, m_Out);
			break;
		default:
			break;
		}
	}

	return m_Out;
}

void Pokemon::InflictDamage(int _damage, queue<string>& _out)
{
	m_CurrentHealth -= _damage; 

	if(m_CurrentHealth <= 0)
		KillPokemon(_out);
}

void Pokemon::Heal(int _amount)
{
	stringstream ss;
	
	ss.str("");
	ss << m_Name << " gained " << _amount << " HP";
	m_Out.push(ss.str());
	m_CurrentHealth += _amount;

	if(m_CurrentHealth > m_Health)
		m_CurrentHealth = m_Health;
}

queue<string> Pokemon::FightWon(const Pokemon& _enemy)
{
	stringstream ss;
	ClearOutput();

	int baseXP = PokemonLoader::GetInstance()->GetPokemonData(_enemy.m_Number).xpGiveaway;
	baseXP += 5*sqrt((float)(16*(_enemy.m_Level + 15)));
	
	ss.str("");
	ss << m_Name << " earned " << baseXP << " xp";
	m_Out.push(ss.str());

	UpdateEffortValue(_enemy);
	UpdateXP(baseXP);

	return m_Out;
}

void Pokemon::UpdateXP(int _xpGain)
{
	m_CurrentXP += _xpGain;

	if(m_CurrentXP >= (m_Level+1) * (m_Level+1) * (m_Level+1))
		LevelUp();
}

void Pokemon::UpdateEffortValue(const Pokemon& _enemy)
{
	PokemonData data = PokemonLoader::GetInstance()->GetPokemonData(_enemy.m_Number);

	m_EVs[HP_INDEX] += data.hp;
	m_EVs[ATK_INDEX] += data.attack;
	m_EVs[DEF_INDEX] += data.defense;
	m_EVs[SPATK_INDEX] += data.spAttack;
	m_EVs[SPDEF_INDEX] += data.spDefense;
	m_EVs[SPD_INDEX] += data.speed;
	
	for( int i = 0; i < STAT_COUNT; i++)
	{
		if(m_EVs[i] < 0)
			m_EVs[i] = MAX_EV;
	}
}

void Pokemon::LevelUp()
{
	stringstream ss;
	
	ss.str("");
	ss << m_Name << " gained a level";
	m_Out.push(ss.str());

	m_Level++;

	if(m_Level == MAX_POKEMON_LEVEL)
		m_CurrentXP = MAX_XP;
	
	if(m_CanEvolve && m_EvolveLevel <= m_Level)
		Evolve();

	string newAttackKey = GetAttackAtLevel(m_Level);

	if(newAttackKey != "")
	{
		PokemonAttack newAttack = PokemonAttack(PokemonLoader::GetInstance()->GetAttackData(newAttackKey));
		
		ss.str("");
		ss << m_Name << " learned " << newAttack;
		m_Out.push(ss.str());

		m_Attacks.push_back(newAttack);
	}

	SetBaseStats(PokemonLoader::GetInstance()->GetPokemonData(m_Number));
}

void Pokemon::Evolve()
{
	stringstream ss;

	ss.str("");
	ss << m_Name << " evolved into ";

	m_Number = (m_Name == "Eevee") ? m_Number + (rand() % 3 + 1) : m_Number + 1;
	PokemonData evolution = PokemonLoader::GetInstance()->GetPokemonData(m_Number);

	m_Name = evolution.name;
	m_CanEvolve = evolution.canEvolve;
	m_EvolveLevel = evolution.evolveLevel;
	
	ss << m_Name;
	m_Out.push(ss.str());

	SetBaseStats(evolution);
	SetCurrentStats();
}

void Pokemon::InflictStatus(const AttackData& _data, queue<string>& _out)
{
	stringstream ss;

	if(!IsAffectedBy(_data.status))
	{
		int randNumber = rand() % 101;
	
		if(randNumber <= _data.statusValue)
		{
			switch(_data.status)
			{
			case POISONED:
			{
				StatusAilmentData newStatus = {POISONED, NO_TURN_LIMIT, 0};
				m_Statuses.push_back(newStatus);

				ss.str("");
				ss << m_Name << " is poisoned";
				_out.push(ss.str());
				break;
			}
			case BURN:
			{
				if(!HasType(FIRE) && !HasType(WATER))
				{
					StatusAilmentData newStatus = {BURN, NO_TURN_LIMIT, 0};
					m_Statuses.push_back(newStatus);
					
					ss.str("");
					ss << m_Name << " is burned";
					_out.push(ss.str());
				}
				break;
			}
			case FREEZE:
			{
				if(!HasType(ICE))
				{
					StatusAilmentData newStatus = { FREEZE, NO_TURN_LIMIT, 0};
					m_Statuses.push_back(newStatus);
					
					ss.str("");
					ss << m_Name << " is frozen solid";
					_out.push(ss.str());
				}
				break;
			}
			case PARALYZE:
			{
				if(!HasType(ELECTRIC))
				{
					m_CurrentSpeed *= 0.25f;
					StatusAilmentData newStatus = { PARALYZE, NO_TURN_LIMIT, 0};
					m_Statuses.push_back(newStatus);
					
					ss.str("");
					ss << m_Name << " is paralyzed";
					_out.push(ss.str());
				}
				break;
			}
			case CONFUSE:
			{
				int maxTurn = rand() % 4 + 1;
				StatusAilmentData newStatus = { CONFUSE, maxTurn, 0};
				m_Statuses.push_back(newStatus);
				
				ss.str("");
				ss << m_Name << " is confused";
				_out.push(ss.str());

				break;
			}
			case SLEEP:
			{
				int maxTurn = rand() % 4 + 1;
				StatusAilmentData newStatus = { SLEEP, maxTurn, 0};
				m_Statuses.push_back(newStatus);
				
				ss.str("");
				ss << m_Name << " fell asleep";
				_out.push(ss.str());

				break;
			}
			case FLINCH:
			{
				m_Waiting = true;
				m_NextAttack = -1;

				break;
			}
			case FAINT:
			{
				ss.str("");
				ss << m_Name << " fainted";
				_out.push(ss.str());

				InflictDamage(m_CurrentHealth, m_Out);
				break;
			}
			default:
				break;
			}
		}
	}
}

void Pokemon::InflictStatModifier(const AttackData& _data, queue<string>& _out)
{
	stringstream ss;
	int randNumber = rand() % 101;

	if(randNumber <= _data.statusValue)
	{
		switch(_data.status)
		{
		case ACY_BOOST:
			ss.str("");
			ss << m_Name << " accuracy's rose";
			_out.push(ss.str());

			m_Accuracy *= 1.1f;
			break;
		case ACY_NERF:
			ss.str("");
			ss << m_Name << " accuracy's fell";
			_out.push(ss.str());

			m_Accuracy *= 0.9f;
			break;
		case ATK_BOOST:
			ss.str("");
			ss << m_Name << " attack's rose";
			_out.push(ss.str());

			m_Attack *= 1.1f;
			break;
		case ATK_NERF:
			ss.str("");
			ss << m_Name << " attack's fell";
			_out.push(ss.str());

			m_Attack *= 0.9f;
			break;
		case DEF_BOOST:
			ss.str("");
			ss << m_Name << " defense's rose";
			_out.push(ss.str());

			m_Defense *= 1.1f;
			break;
		case DEF_NERF:
			ss.str("");
			ss << m_Name << " defense's fell";
			_out.push(ss.str());

			m_Defense *= 0.9f;
			break;
		case SP_BOOST:
			ss.str("");
			ss << m_Name << " special's rose";
			_out.push(ss.str());

			m_SpAttack *= 1.1f;
			m_SpDefense *= 1.1f;
			break;
		case SP_NERF:
			ss.str("");
			ss << m_Name << " special's fell";
			_out.push(ss.str());

			m_SpAttack *= 0.9f;
			m_SpDefense *= 0.9f;
			break;
		case SPD_BOOST:
			ss.str("");
			ss << m_Name << " speed's rose";
			_out.push(ss.str());

			m_Speed *= 1.1f;
			break;
		case SPD_NERF:
			ss.str("");
			ss << m_Name << " speed's fell";
			_out.push(ss.str());

			m_Speed *= 0.9f;
			break;
		default:
			cout << "STAT MODIFIER ERROR : There is no such stat to modify" << endl;
			break;
		}
	}
}

void Pokemon::ClearOutput()
{
	while(!m_Out.empty())
	{
		m_Out.pop();
	}
}

void Pokemon::KillPokemon(queue<string>& _out)
{
	stringstream ss;

	m_CurrentHealth = 0;
	m_Statuses.clear();
	
	ss.str("");
	ss << m_Name << " fainted";
	_out.push(ss.str());
	
	StatusAilmentData newStatus = { FAINT, NO_TURN_LIMIT, 0};
	m_Statuses.push_back(newStatus);
}

int Pokemon::HPCalculation(int _baseStat, int _statIndex)
{
	return ((m_IVs[_statIndex] + _baseStat + (sqrt((float)m_EVs[_statIndex]) / 8.0f) + 50) * m_Level/50.0f) + 10;
}

int Pokemon::StatCalculation(int _baseStat, int _statIndex) 
{
	return ((m_IVs[_statIndex] + _baseStat + (sqrt((float)m_EVs[_statIndex]) / 8.0f)) * m_Level/50.0f) + 5;
}

void Pokemon::SetCurrentStats()
{
	m_CurrentHealth = m_Health;
	m_CurrentAttack = m_Attack;
	m_CurrentDefense = m_Defense;
	m_CurrentSpAttack = m_SpAttack;
	m_CurrentSpDefense = m_SpDefense;
	m_CurrentSpeed = m_Speed;
	m_Accuracy = 1.0f;
}

int Pokemon::DamageCalculation(PokemonAttack& _attack, const Pokemon& _enemy)
{
	int attack, defense = 0;

	attack = _attack.IsPhysical() ? m_Attack : m_SpAttack;
	defense = _attack.IsPhysical() ? _enemy.m_Defense : _enemy.m_SpDefense; 

	float modifier = ModifierCalculation(_attack, _enemy);
	float damage = ( ((2*m_Level + 10) / 250.0f) * (attack/(float)defense) * (_attack.GetAttackData().power) + 2) * modifier;

	return damage;
}

float Pokemon::ModifierCalculation(PokemonAttack& _attack, const Pokemon& _enemy)
{
	stringstream ss;
	float stab, typeEffectiveness, critical, random;

	stab = HasType(_attack.GetAttackData().type) ? 1.5f : 1.0f;
	typeEffectiveness = TypeModifier(_attack, _enemy);
	random = (rand() % 16 + 85) / 100.0f;
	
	critical = CriticalHitCalculation();
	_attack.SetCritical(critical == 2);

	if(_attack.GetCritical())
	{
		ss.str("");
		ss << "It's a critical hit";
		m_Out.push(ss.str());
	}

	return stab * typeEffectiveness * critical * random;
}

int Pokemon::CriticalHitCalculation() const
{
	int random = rand() % 101;

	return random < CRIT_CHANCE ? 2 : 1;
}

float Pokemon::TypeModifier(PokemonAttack& _attack, const Pokemon& _enemy)
{
	stringstream ss;
	float modifier = 1.0f;

	for(int i = 0; i < MAX_POKEMON_TYPE; i++)
	{
		if(_enemy.m_Types[i] != TYPE_NONE)
			modifier *= PokemonLoader::GetInstance()->GetTypeEffectiveness((int)_attack.GetAttackData().type, (int)_enemy.m_Types[i]);
	}

	if (abs(modifier) < EPSILON)
	{
		_attack.SetMiss(true);

		ss.str("");
		ss << _attack << " missed";
		m_Out.push(ss.str());

		return 0.0f;
	}
	else if (abs(modifier - 0.25f) < EPSILON)
	{
		_attack.SetNotVeryEffective(true);
		
		ss.str("");
		ss << "It's not very effective";
		m_Out.push(ss.str());
		return 0.25f;
	}
	else if (abs(modifier - 0.5f) < EPSILON)
	{
		_attack.SetNotVeryEffective(true);
		
		ss.str("");
		ss << "It's not very effective";
		m_Out.push(ss.str());
		return 0.5f;
	}
	else if (abs(modifier - 1.0f) < EPSILON)
	{
		return 1.0f;
	}
	else if (abs(modifier - 2.0f) < EPSILON)
	{
		_attack.SetSuperEffective(true);
		
		ss.str("");
		ss << "It's super effective";
		m_Out.push(ss.str());
		return 2.0f;
	}
	else
	{
		_attack.SetSuperEffective(true);
		
		ss.str("");
		ss << "It's super effective";
		m_Out.push(ss.str());
		return 4.0f;
	}
}

void Pokemon::ForgetAttack(int _index)
{
	m_Attacks[_index] = m_Attacks[m_Attacks.size()-1];
	m_Attacks.pop_back();
}

bool Pokemon::CanAttack(queue<string>& _out)
{
	stringstream ss;
	ClearOutput();

	vector<StatusAilmentData>::iterator iter;

	for(iter = m_Statuses.begin(); iter != m_Statuses.end(); iter++)
	{
		iter->turnAffected++;

		switch(iter->status)
		{
		case FREEZE:
		{
			int randNumber = rand() % 101;
			
			if(randNumber < THAW_ACCURACY)
			{
				ss.str("");
				ss << m_Name << " is no longer frozen";
				_out.push(ss.str());
				iter = m_Statuses.erase(iter);
			}
			else
			{
				ss.str("");
				ss << m_Name << " is frozen solid";
				_out.push(ss.str());
				return false;
			}
			break;
		}
		case SLEEP:
			if(iter->turnAffected == iter->maxTurnAffected)
			{
				ss.str("");
				ss << m_Name << " woke up";
				_out.push(ss.str());
				iter = m_Statuses.erase(iter);
			}
			else
			{
				ss.str("");
				ss << m_Name << " is fast asleep";
				_out.push(ss.str());
				return false;
			}
			break;
		case FLINCH:
			iter = m_Statuses.erase(iter);

			ss.str("");
			ss << m_Name << " can't move";
			_out.push(ss.str());
			return false;
			break;
		case PARALYZE:
		{
			int randNumber = rand() % 101;

			if(randNumber < PARALYZE_ACCURACY)
			{
				ss.str("");
				ss << m_Name << " is fully paralyzed";
				_out.push(ss.str());
				return false;
			}
			break;
		}
		case CONFUSE:
		{
			if(iter->turnAffected == iter->maxTurnAffected)
			{
				ss.str("");
				ss << m_Name << " is no longer confused";
				_out.push(ss.str());

				iter = m_Statuses.erase(iter);
			}
			else if(IsConfused())
			{
				ss.str("");
				ss << m_Name << " hurts itself in confusion";
				m_Out.push(ss.str());

				AttackData confused = {0, "", NORMAL, 0, 40, 100, 0, STATUS_NONE, 0, METEOR};
				PokemonAttack confusedAttack = PokemonAttack(confused);

				InflictDamage(m_Health/8.0f, _out);

				return false;
			}
		}
		default:
			break;
		}

		if(iter == m_Statuses.end())
			break;
	}

	return true;
}

bool Pokemon::IsConfused() const
{
	if(IsAffectedBy(CONFUSE))
	{
		int randNumber = rand() % 101;
		return randNumber < CONFUSION_ACCURACY ? true : false;
	}

	return false;
}

bool Pokemon::IsAffectedBy(const StatusEffect& _effect) const
{
	for(int i = 0; i < m_Statuses.size(); i++)
	{
		if( m_Statuses[i].status == _effect)
			return true;
	}

	return false;
}

bool Pokemon::HasType(const PokemonType& _type) const
{
	for(int i = 0; i < MAX_POKEMON_TYPE; i++)
	{
		if(m_Types[i] == _type)
			return true;
	}

	return false;
}

string Pokemon::GetAttackAtLevel(int _level) const
{
	vector<LevelUpData> levelUpChart = PokemonLoader::GetInstance()->GetLevelUpChart(m_Number);

	for(int i = 0; i < levelUpChart.size(); i++)
	{
		if(levelUpChart[i].level == _level)
			return levelUpChart[i].attack;
	}

	return "";
}

int Pokemon::GetAttackIndex(string _attackName) const
{
	for(int i = 0; i < m_Attacks.size(); i++)
	{
		if(m_Attacks[i].GetAttackData().name == _attackName)
			return i;
	}

	return -1;
}

void Pokemon::RemoveAllStatus()
{
	m_Statuses.clear();
}